﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace Creative85.Framework.Utilities
{
	public static class ModelUtility
	{
		private static Dictionary<string, List<PropertyInfo>> typeCaches = new Dictionary<string, List<PropertyInfo>>();

		/// <summary>
		/// 深复制
		/// </summary>
		/// <param name="original"></param>
		/// <returns></returns>
		public static object Copy(object original)
		{
			object target;
			BinaryFormatter formatter = new BinaryFormatter();
			using (var ms = new MemoryStream())
			{
				formatter.Serialize(ms, (object)original);
				ms.Seek(0, SeekOrigin.Begin);
				target = formatter.Deserialize(ms);
			}
			return target;
		}
		/// <summary>
		/// 深复制
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="original"></param>
		/// <returns></returns>
		public static T Copy<T>(T original) where T : class
		{
			T target = Copy((object)original) as T;
			return target;
		}

		/// <summary>
		/// 复制对象的属性
		/// </summary>
		/// <param name="original"></param>
		/// <param name="target"></param>
		/// <param name="allowProperties"></param>
		/// <param name="denyProperties"></param>
		public static void CopyValue(this object original, object target, IEnumerable<string> allowProperties = null, IEnumerable<string> denyProperties = null)
		{
			Type originalType = original.GetType(),
				targetType = target.GetType();
			string originalTypeName = originalType.FullName,
				targetTypeName = targetType.FullName;
			List<PropertyInfo> originalProperties = null,
				targetProperties = null;
			if (!typeCaches.TryGetValue(originalTypeName, out originalProperties))
			{
				originalProperties = originalType.GetProperties().OrderBy(x => x.Name).ToList();
				typeCaches.Add(originalTypeName, originalProperties);
			}
			if (!typeCaches.TryGetValue(targetTypeName, out targetProperties))
			{
				targetProperties = originalType.GetProperties().OrderBy(x => x.Name).ToList();
				typeCaches.Add(targetTypeName, targetProperties);
			}
			PropertyInfo originalProperty, targetProperty;
			object originalValue;
			foreach (PropertyInfo property1 in originalProperties)
			{
				originalProperty = property1;
				targetProperty = targetProperties.FirstOrDefault(x => x.Name.Equals(originalProperty.Name, StringComparison.OrdinalIgnoreCase));
				if (
					targetProperty != null &&
					(allowProperties == null || allowProperties.Contains(originalProperty.Name, StringComparer.OrdinalIgnoreCase)) &&
					(denyProperties == null || !denyProperties.Contains(originalProperty.Name, StringComparer.OrdinalIgnoreCase))
				)
				{
					originalValue = originalProperty.GetValue(original, null);
					targetProperty.SetValue(target, originalValue, null);
				}
			}
		}


        /// <summary>
        /// 获取变量名。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="exp"></param>
        /// <returns></returns>
        public static string GetVarName<T>(System.Linq.Expressions.Expression<Func<T, T>> exp)
        {
            return ((System.Linq.Expressions.MemberExpression)exp.Body).Member.Name;
        }
        /// <summary>
        /// 获取变量名。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="var_name"></param>
        /// <param name="exp"></param>
        /// <returns></returns>
        public static string GetVarName<T>(this T var_name, System.Linq.Expressions.Expression<Func<T, T>> exp)
        {
            return ((System.Linq.Expressions.MemberExpression)exp.Body).Member.Name;
        }
	}
}
